import asyncio
import os
import shutil
from googletrans import Translator
from bs4 import BeautifulSoup

"""
功能：
1. 翻译目录下所有HTML文件
2. 异步翻译HTML文件
3. 复制其它文件
4. 翻译失败的内容，保留原内容
5. 翻译失败的文件，不会被保存到输出目录
6. 缓存翻译的结果，避免重复翻译。
"""

# 初始化翻译器
translator = Translator()

# 缓存翻译结果
tranMap = {}
# 缓存翻译内容的最大长度
mapTextMaxLength = 50

failed_files = []


async def translate_text(text: str, lang: str = "zh-cn") -> tuple[str, bool]:
    """
    异步翻译函数

    Args:
        text (str): 被翻译的内容
        lang (str, optional): 目标语言. Defaults to 'zh-cn'.

    Returns:
        翻译结果
    """
    try:
        if text.strip():
            if text in tranMap:
                return tranMap[text], True
            result = await translator.translate(text, dest=lang)
            if len(text) <= mapTextMaxLength:
                tranMap[text] = result.text
            return result.text, True
        return text, True
    except Exception as e:
        print(f"翻译错误: {e.__str__()}")
        return text, False


def need_translate(tag) -> bool:
    if not tag.strip():
        return False

    if tag.parent.name in [
        "script",
        "style",
        "head",
        "title",
    ]:
        return False

    # 排除被标记为notranslate的标签
    parent_tag = tag.parent
    while parent_tag:
        clazz = parent_tag.attrs.get("class")
        if clazz is not None and "notranslate" in clazz:
            return False
        parent_tag = parent_tag.parent

    return True


async def translate_html(input_file, output_file, lang="zh-cn"):
    # 读取HTML文件
    with open(input_file, "r", encoding="utf-8") as file:
        soup = BeautifulSoup(file, "html.parser")

    # 遍历所有文本节点并翻译
    tasks = []
    for tag in soup.find_all(string=True):
        # 排除脚本、样式、标题
        if need_translate(tag):
            tasks.append(translate_text(tag, lang))

    # 并行执行翻译任务
    translated_texts = await asyncio.gather(*tasks)

    # 将翻译结果替换回HTML
    success = True
    text_nodes = [tag for tag in soup.find_all(string=True) if need_translate(tag)]
    for node, translated in zip(text_nodes, translated_texts):
        if not translated[1]:
            success = False
        node.replace_with(translated[0])

    if success:
        # 保存翻译后的文件
        with open(output_file, "w", encoding="utf-8") as file:
            file.write(str(soup))
    else:
        failed_files.append(f"{input_file},{output_file}")


async def translate_directory(
    input_dir: str, output_dir: str, lang: str = "zh-cn"
) -> None:
    """
    翻译目录下所有HTML文件

    Args:
        input_dir (str): 输入目录
        output_dir (str): 输出目录
        lang (str, optional): 目标语言. Defaults to 'zh-cn'.
    """

    # 创建目标目录
    os.makedirs(output_dir, exist_ok=True)
    # 遍历输入目录
    for file_name in os.listdir(input_dir):
        input_file = os.path.join(input_dir, file_name)
        output_file = os.path.join(output_dir, file_name)
        if os.path.isdir(input_file):
            # 递归翻译子目录
            await translate_directory(input_file, output_file, lang)
        elif file_name.endswith(".html"):
            # 翻译HTML文件
            if os.path.exists(output_file):
                # 输出文件已存在，跳过
                continue
            print(f"翻译文件: {input_file}")
            await translate_html(input_file, output_file, lang)
        else:
            # 复制其它文件
            if os.path.exists(output_file):
                # 输出文件已存在，跳过
                continue
            print(f"复制文件: {input_file}")
            shutil.copyfile(input_file, output_file)


def save_failed_files():
    """
    保存失败的文件到缓存文件中
    """
    with open("failed_files.txt", "w", encoding="utf-8") as file:
        for file_name in failed_files:
            file.write(file_name + "\n")


def test():
    # input_file = "./test/aero.html"  # 输入文件
    # output_file = "./test/aero_translated.html"  # 输出文件
    input_file = "./test/with_code.html"  # 输入文件
    output_file = "./test/with_code_translated.html"  # 输出文件
    asyncio.run(translate_html(input_file, output_file, lang="zh-cn"))


# 运行程序
if __name__ == "__main__":
    # 被翻译的目录
    input_dir = "./documentation"
    # 翻译后的目录
    output_dir = "./translated"
    # 目标语言
    lang = "zh-cn"
    asyncio.run(translate_directory(input_dir, output_dir, lang=lang))
    # test()
    save_failed_files()
